package jmine.tec.hydra.api;

import java.util.List;

import jmine.tec.hydra.domain.HydraComment;
import jmine.tec.hydra.domain.HydraSystem;
import jmine.tec.hydra.domain.StatusHydraRequest;
import bancosys.tec.persist.Persistable;
import bancosys.tec.rtm.impl.exception.domain.ExceptionRecord;
import bancosys.tec.utils.date.Timestamp;

/**
 * Inteface de um HydraRequest. Toda requisição Hydra é representada por um request. Uma requisição começa com uma ação raiz, e as demais
 * ações são geradas a partir desta primeira e assim por diante. No caso ideal, cada ação é executada com sucesso e o request acaba em
 * sucesso. Caso ocorra um erro de negócio, o status de ao menos uma action se torna "pendente". Uma action pendente deve ser resolvida
 * manualmente pelo usuário, que deve então marcar a ação como resolvida. Uma vez que todas as ações pendentes são resolvidas o request
 * tornar-se-á resolvido também. Caso ocorra uma falha grave (erro de IO, npe, erro na execução do script...), a action sendo executada será
 * salva com status de falha, e o processamento da requisição irá parar imediatamente, resultando em erro. Se uma exception for jogada do
 * método execute(action) a transação em que ela ocorre deve ser revertida, no caso de chamadas de sistema, e mensagens de um mdb não devem
 * ser consumidas. Isso deve ocorrer apenas quando ocorrer uma falha grave na persistência e continuar geraria perda de informação.
 * 
 * @author lundberg
 */
public interface HydraRequest extends Persistable {

    /**
     * Executa um HydraRequest. Uma requisição terminada sem exceções pode não ter sido um sucesso pleno, é possível que seu status seja
     * "pendente", ou seja, ainda precisa de alguma intervenção manual do usuário. Exception é jogada apenas em falhas graves e inesperadas.
     * A requisição resultante pode não estar salva, caso nada relevante tenha acontecido (nenhuma mensagem tenha sido gerada, nem tenha
     * ocorrido erro algum).
     * 
     * @param action action raiz do request
     * @return request, para method chaining
     */
    HydraRequest execute(HydraAction action);

    /**
     * Hora em que foi iniciado o processamento da requisição
     * 
     * @return timestamp
     */
    Timestamp getRequestStart();

    /**
     * Hora em que foi terminado o processamento da requisição
     * 
     * @return timestamp
     */
    Timestamp getRequestEnd();

    /**
     * Status a requisição
     * 
     * @return status
     */
    StatusHydraRequest getStatus();

    /**
     * Comments relativos à requisição
     * 
     * @return comments
     */
    List<HydraComment> getComments();

    /**
     * Ações executadas durante o processamento da requisição
     * 
     * @return actions
     */
    List<HydraAction> getActions();

    /**
     * Registro de exceção gerada durante o processamento da requisição.
     * 
     * @return ExceptionRecord
     */
    ExceptionRecord getExceptionRecord();

    /**
     * Usuário que iniciou a execução da requisição.
     * 
     * @return String
     */
    String getUser();

    /**
     * Encontra o HydraSystem relacionado a este request.
     * 
     * @return o HydraSystem
     */
    HydraSystem getSystem();

    /**
     * Encontra as mensagens tratadas pela requisição
     * 
     * @return HydraMessages
     */
    List<HydraMessage> getMessages();

    /**
     * Encontra a especificação utilizada para tratar a requisição
     * 
     * @return HydraSpecification
     */
    HydraSpecification getSpecification();

    /**
     * Obtém o sumário da requisição.
     * 
     * @return String
     */
    String getSummary();

    /**
     * Marca a action como resolvida e salva a requisição.
     * 
     * @param action action
     */
    void markPendingActionSolved(HydraAction action);
}